hive 数组拼字符串 hive数组函数 |
您所在的位置:网站首页 › hive 字符替换函数 › hive 数组拼字符串 hive数组函数 |
一、炸裂函数 针对一行数据,输出多行数据,主要用于map,array这种的 根据一个例子来看: friends 是一个array数组students 是一个mapaddress是一个structexplode函数以array类型数据输入,然后对数组中的数据进行迭代,返回多行结果,一行一个数组元素值。 作用于array: arrayCol :array字段的名称colName1 :array字段的别名,随便起-- 语法是这样 select explode(arrayCol) as colName1 from tablename举例: select explode(friends) from teacher
作用于map: mapcol :map字段名称key1:key的别名 随便起value1:value的别名 随便起select explode(mapcol) as (key1,value1) from tablename;举例: select explode(students) from teacher
2)posexplode函数 相对于 返回多行结果,一行一个数组元素值。会返回元素在集合中的位置 区别: posexplode只能用于array,而explode可以用于array,mapposexplode还会返回元素在集合中的位置select posexplode(friends) from teacher
3)Lateral View 通常与UDTF配合使用,Lateral View可以将UDTF应用到源表的每行数据,将每行数据转换为一行或者多行,并将源表中每行的输出结果与该行连接起来,形成一个虚拟表。 那么,解决的问题到底是什么? sql语法: ⚠️lateral view 一定要在udtf函数的前面⚠️虚拟表别名一定要加,不然会报错select [col1,col2,col3……] from 表名 lateral view udtf(expression) 虚拟表别名举例: select name,friends,address from teacher lateral view explode(friends) p1先看原来的数据:
需求是:
select cate,count(*)from ( select movie, cate from (select movie,split(category,',') cates from movie_info) t1 lateral view explode(cates) tmp as cate )t2 group by cate;二、窗口函数 每行数据都能作为一个窗口,每个窗口都会进行范围的计算操作,并将计算结果返回当前行的一个新的字段。 可以是聚合(sum max min)等等操作,也可以是其他函数操作。 ⭐️常用窗口可划分为如下几类:聚合函数、跨行取值函数、排名函数。
举例:定义窗口函数基于行,使用聚合函数(sum)的,窗口的规则是字段A 负无穷到当前行。计算过程是怎么样的? 首先对字段A从小到大进行排序。 1.按照排序后的一行一行作为窗口,从第一行开始,第一行的字段A最小,发现自己是最小的,那就当前行做为第一个窗口,计算结果只有本身,结果返回给第一行。 2.从第二行开始继续寻找,负无穷到当前行的,第二个窗口包含第一行、第二行数据,做范围内运算,sum=第一行的字段A+第二行的字段A,结果返回给第二行。 第三个窗口,包含第一行、第二行、第三行数据,那么计算sum=第一行字段A+第二行字段A+第三行字段A。 以此类推。。。。 最后一行的返回的计算结果一定是所有行字段A的总和 那这跟直接sql写sum()+group by 有什么区别吗? ⭐️区别在于,每行数据都会参与到计算中来,同时得到窗口计算的结果,我们直接写sql语句调用sum()只会返回最终结果,相当于只有最后一个窗口的值。 ⭐️1)窗口规则 between and:between相当重要的原因是按照什么样的规则定义窗口。 unbounded preceding 表示负无穷current row 基于行的方式表示当前行,基于值的方式表示当前值unbounded following 表示正无穷[num] preceding 基于行的方式 表示当前行的前几行,基于值的方式 表示当前值减去num[num] following 基于值的方式 表示当前行的后几行,基于值的方式表示当前值加上num⚠️ and 前后要注意sql的写法 如果前面写,current row,后面不允许写[num] preceding如果使用基于值的方式,使用 preceding[num]或者[num] following,一定要保证划分窗口的字段属于数字类型2)基于行举例: between unbounded preceding and cureent now 表示负无穷到当前行 做为一个窗口order_id为1的发现order_date 小于自己的没有,只有自己,所以第一个窗口只包含当前行ordr_id为2的先查找,order_date小于等于当前行的,发现order_id为1的算一个,所以第二个窗口包含两行,是order_id为1的以及order_id为2的。 做窗口内的范围内运算(由于是sum,则相加)=20+10ordr_id为3=10+20+10以此类推。。。
3)基于值 跟基于行最大的区别是什么? between规则应用的不一样 同样都是between unbounded preceding and cureent now 基于行的含义是负无穷到当前行,而基于值的含义是负无穷到当前值 也就说基于行 会以自己的行 为终点,但是基于值 会 查找某个字段 小于等于自己的,自己的行不一定是终点。 如下图所示: order_id为1的查找order_date小于等于自己的,只有本身,total_amount为自己 order_id为2的查找order_date小于等于自己的,有order_id为1,order_id为2,order_id为3,total_amount为10+20+10 order_id为3的查找order_date小于等于自己的,有order_id为1,order_id为2,order_id为3,total_amount为10+20+10 如果不开分区,那么窗口的计数从整个数据的开始到结尾 如果开了分区,那么一个分区内窗口计数从分区头到分区尾 说白了,第二个分区的实际数据即使在表的中间,也有可能属于第一个窗口 字段1,字段2 不用说了,就是显示的字段 ⭐️ sum(字段3) 是基于窗口做什么操作,这个表示是基于每个窗口对 sum3字段做求和操作 ⭐️ over()表示是什么样的窗口 字段2:针对字段2进行划分窗口 rows:表示基于行 between unbounded preceding and current row:表示负无穷到最后一行 select 字段1,字段2, ..., sum(字段3) over(字段2 rows between unbounded preceding and current row) as 新字段1基于值的语法:range:表示基于值unbounded preceding and unbounded following: 表示负无穷到正无穷select 字段1,字段2, ..., sum(字段3) over(字段2 range between unbounded preceding and unbounded following) as 新字段1加分区:跟基于行 基于值没有关系 partition by 字段1 表示针对字段1做分区select 字段1,字段2, ..., sum(字段3) over(partition by 字段1 字段2 range between unbounded preceding and current row) as 新字段16)缺省下情况:就什么都不加,over(字段)相当于 基于行做窗口,范围是负无穷到正无穷,相当于所有字段作为一个窗口over(order by 字段) 排序后基于值做窗口,范围是负无穷到当前行⭐️无论基于行还是基于值, 不加order by,没有任何意义(因为你都不知道上一行和下一行的值有没有关联),做范围内计算也是白瞎支持以下几种,不再多阐述 max min sum avg count 8)跨行取值函数分别包括: lag和lead(不支持自定义窗口): lag(): 按照 所在行的偏移量 取 前面的第几行 lead(): 按照 所在行的偏移量 取 后面的第几行 first_value和last_value(支持自定义窗口): first_value():当前窗口内所有行数据中的最小值last_value(): 当前窗口内所有行数据中的最大值⚠️要注意,lag和lead不能使用自定义窗口,因为已经规定好了具体某一行与当前行作为一个窗口,不能再定义是负无穷到正无穷这样自定义的规则。 lag和lead: 语法: lag() : 字段3:结果字段 1: 取当前行前面的前1行 ‘1970-01-01’:当前所在行数取不够前面的行,取默认行(比如取前5行,但是当前行数是第四行,就取值为(‘1970-01-01’)的所在行 lead : 同上 语法如下: select 字段1,字段2,字段3 lag(字段3,向前的具体行数,'默认值') over (.....) 别名1, lead(字段3,向后的具体行数,'默认值') over (.....) 别名2, from table举例: 现在要获取当前订单的上一个订单的时间跟下一个订单的时间(统计一下时间间隔) 可以看到,lag根据order_date做一个跨行,先按照时间排序(over order by )后 取前面的一行,跟后面的一行,分别做为last_date 和 next_date 字段first_value和last_value: 语法: first_value(字段3,FALSE) 字段3表示具体取哪个字段的值,false表示允许null的值作为结果,如果窗口内某一行是null值,结果就是nullselect 字段1,字段2,字段3 first_value(字段3,FALSE) over(order by 字段3) last_date, last_value(字段3,FALSE) over(order by 字段3) next_date from table_name举例: 获取每个用户订单的最早的下单时间(first_date) 那么就可以先以用户id分区,如下的user_id的就包含三个窗口,每个窗口最小值就是2022-01-01,所以得出user_id所有的订单中最早的日期是2022-01-01rank() 对某个值做个排名 dense_rank() 如果相同的值,给一样的名次 row_number() 如果相同的值,按照插入表的顺序分名次 1)表结构 order_id user_id user_name order_date order_amount 1 1001 小元 2022-01-01 10 2 1002 小海 2022-01-02 15 3 1001 小元 2022-02-03 23 4 1002 小海 2022-01-04 29 5 1001 小元 2022-01-05 46 2)建表语句 create table order_info ( order_id string, --订单id user_id string, -- 用户id user_name string, -- 用户姓名 order_date string, -- 下单日期 order_amount int -- 订单金额 ); insert overwrite table order_info values ('1', '1001', '小元', '2022-01-01', '10'), ('2', '1002', '小海', '2022-01-02', '15'), ('3', '1001', '小元', '2022-02-03', '23'), ('4', '1002', '小海', '2022-01-04', '29'), ('5', '1001', '小元', '2022-01-05', '46'), ('6', '1001', '小元', '2022-04-06', '42'), ('7', '1002', '小海', '2022-01-07', '50'), ('8', '1001', '小元', '2022-01-08', '50'), ('9', '1003', '小辉', '2022-04-08', '62'), ('10', '1003', '小辉', '2022-04-09', '62'), ('11', '1004', '小猛', '2022-05-10', '12'), ('12', '1003', '小辉', '2022-04-11', '75'), ('13', '1004', '小猛', '2022-06-12', '80'), ('14', '1003', '小辉', '2022-04-13', '94');2. 需求1)统计每个用户截至每次下单的累积下单总额 期望结果: order_id user_id user_name order_date order_amount sum_so_far 1 1001 小元 2022-01-01 10 10 5 1001 小元 2022-01-05 46 56 8 1001 小元 2022-01-08 50 106 3 1001 小元 2022-02-03 23 129 6 1001 小元 2022-04-06 42 171 2 1002 小海 2022-01-02 15 15 4 1002 小海 2022-01-04 29 44 7 1002 小海 2022-01-07 50 94 9 1003 小辉 2022-04-08 62 62 10 1003 小辉 2022-04-09 62 124 12 1003 小辉 2022-04-11 75 199 14 1003 小辉 2022-04-13 94 293 11 1004 小猛 2022-05-10 12 12 13 1004 小猛 2022-06-12 80 92 (2)需求实现 select order_id,user_id, user_name,order_date,order_amount, sum(order_amount) over(partition by user_id order by order_date rows between unbounded preceding and current row) sum_so_far from order_info;2)统计每个用户截至每次下单的当月累积下单总额 (1)期望结果 order_id user_id user_name order_date order_amount sum_so_far 1 1001 小元 2022-01-01 10 10 5 1001 小元 2022-01-05 46 56 8 1001 小元 2022-01-08 50 106 3 1001 小元 2022-02-03 23 23 6 1001 小元 2022-04-06 42 42 2 1002 小海 2022-01-02 15 15 4 1002 小海 2022-01-04 29 44 7 1002 小海 2022-01-07 50 94 9 1003 小辉 2022-04-08 62 62 10 1003 小辉 2022-04-09 62 124 12 1003 小辉 2022-04-11 75 199 14 1003 小辉 2022-04-13 94 293 11 1004 小猛 2022-05-10 12 12 13 1004 小猛 2022-06-12 80 80 (2)需求实现 select order_id, user_id, user_name, order_date, order_amount, sum(order_amount) over(partition by user_id,substring(order_date,1,7) order by order_date rows between unbounded preceding and current row) sum_so_far from order_info;3)统计每个用户每次下单距离上次下单相隔的天数(首次下单按0天算) (1)期望结果 order_id user_id user_name order_date order_amount diff 1 1001 小元 2022-01-01 10 0 5 1001 小元 2022-01-05 46 4 8 1001 小元 2022-01-08 50 3 3 1001 小元 2022-02-03 23 26 6 1001 小元 2022-04-06 42 62 2 1002 小海 2022-01-02 15 0 4 1002 小海 2022-01-04 29 2 7 1002 小海 2022-01-07 50 3 9 1003 小辉 2022-04-08 62 0 10 1003 小辉 2022-04-09 62 1 12 1003 小辉 2022-04-11 75 2 14 1003 小辉 2022-04-13 94 2 11 1004 小猛 2022-05-10 12 0 13 1004 小猛 2022-06-12 80 33 (2)需求实现 select order_id,user_id,user_name,order_date,order_amount, nvl(datediff(order_date,last_order_date),0) diff from ( select order_id,user_id, user_name,order_date, order_amount, lag(order_date,1,null) over(partition by user_id order by order_date) last_order_date from order_info )t14)查询所有下单记录以及每个用户的每个下单记录所在月份的首末次下单日期 (1)期望结果 order_id user_id user_name order_date order_amount first_date last_date 1 1001 小元 2022-01-01 10 2022-01-01 2022-01-08 5 1001 小元 2022-01-05 46 2022-01-01 2022-01-08 8 1001 小元 2022-01-08 50 2022-01-01 2022-01-08 3 1001 小元 2022-02-03 23 2022-02-03 2022-02-03 6 1001 小元 2022-04-06 42 2022-04-06 2022-04-06 2 1002 小海 2022-01-02 15 2022-01-02 2022-01-07 4 1002 小海 2022-01-04 29 2022-01-02 2022-01-07 7 1002 小海 2022-01-07 50 2022-01-02 2022-01-07 9 1003 小辉 2022-04-08 62 2022-04-08 2022-04-13 10 1003 小辉 2022-04-09 62 2022-04-08 2022-04-13 12 1003 小辉 2022-04-11 75 2022-04-08 2022-04-13 14 1003 小辉 2022-04-13 94 2022-04-08 2022-04-13 11 1004 小猛 2022-05-10 12 2022-05-10 2022-05-10 13 1004 小猛 2022-06-12 80 2022-06-12 2022-06-12 (2)需求实现 select order_id,user_id,user_name,order_date,order_amount, first_value(order_date) over(partition by user_id,substring(order_date,1,7) order by order_date) first_date, last_value(order_date) over(partition by user_id,substring(order_date,1,7) order by order_date rows between unbounded preceding and unbounded following) last_date from order_info;5)为每个用户的所有下单记录按照订单金额进行排名 (1)期望结果 order_id user_id user_name order_date order_amount rk drk rn 8 1001 小元 2022-01-08 50 1 1 1 5 1001 小元 2022-01-05 46 2 2 2 6 1001 小元 2022-04-06 42 3 3 3 3 1001 小元 2022-02-03 23 4 4 4 1 1001 小元 2022-01-01 10 5 5 5 7 1002 小海 2022-01-07 50 1 1 1 4 1002 小海 2022-01-04 29 2 2 2 2 1002 小海 2022-01-02 15 3 3 3 14 1003 小辉 2022-04-13 94 1 1 1 12 1003 小辉 2022-04-11 75 2 2 2 9 1003 小辉 2022-04-08 62 3 3 3 10 1003 小辉 2022-04-09 62 3 3 4 13 1004 小猛 2022-06-12 80 1 1 1 11 1004 小猛 2022-05-10 12 2 2 2 (2)需求实现 select order_id,user_id,user_name,order_date,order_amount, rank() over(partition by user_id order by order_amount desc) rk, dense_rank() over(partition by user_id order by order_amount desc) drk, row_number() over(partition by user_id order by order_amount desc) rn from order_info;
|
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |